# -*- coding: utf-8 -*-
"""
str.format() 方法的专用回调处理器

处理字符串格式化的不同场景：
1. format(**data) - 使用 mc::format_dict
2. format(**{"key": "val"}) - 展开为 sformat 参数
3. format(key="val") - 使用 sformat
"""

from typing import Optional
from mcpy.ir.expressions.call import IRCall
from mcpy.ir.expressions.literals import IRDict
from mcpy.ir.expressions.access import IRAttribute
from mcpy.ir.expressions.basic import IRConstant
from mcpy.codegen.core.context import CodeGenContext
from mcpy.codegen.core.emitter import EmitResult
from mcpy.codegen.configs.operators import get_operator_precedence


class StrFormatCallback:
    """str.format() 方法的回调处理器"""

    def emit(self, node: IRCall, context: CodeGenContext) -> Optional[EmitResult]:
        """生成 str.format() 调用的代码

        Args:
            node: IRCall 节点
            context: 代码生成上下文

        Returns:
            EmitResult 或 None（如果不处理）
        """
        from mcpy.codegen.core.generator import get_global_generator

        generator = get_global_generator()

        # 确保是方法调用
        if not isinstance(node.func, IRAttribute):
            return None

        # 获取格式字符串（self）
        format_str_node = node.func.value

        # 检查是否是字符串字面量
        if isinstance(format_str_node, IRConstant) and isinstance(
            format_str_node.value, str
        ):
            # 字符串字面量，使用引号包裹
            format_str_code = f'"{format_str_node.value}"'
        else:
            # 动态表达式
            format_str_code = generator.generate_expression(
                format_str_node, context, parent_precedence=100
            )

        # 处理不同的参数情况
        has_starargs = node.starargs is not None
        has_keywords = node.keywords and len(node.keywords) > 0

        if has_starargs:
            # 情况1: 有 **kwargs 参数
            if isinstance(node.starargs, IRDict):
                # **{"key": "val"} - 字面量字典，展开为命名参数
                return self._emit_with_literal_dict(
                    format_str_code, node.starargs, node.keywords, context
                )
            else:
                # **data - 变量字典，使用 mc::format_dict
                return self._emit_with_variable_dict(
                    format_str_code, node.starargs, node.keywords, context
                )
        elif has_keywords:
            # 情况2: 只有普通关键字参数，使用 sformat
            return self._emit_with_keywords(format_str_code, node.keywords, context)
        else:
            # 情况3: 没有参数，直接返回字符串
            return EmitResult(
                code=f"{format_str_code}", precedence=get_operator_precedence("call")
            )

    def _emit_with_literal_dict(
        self,
        format_str: str,
        dict_node: IRDict,
        keywords: list,
        context: CodeGenContext,
    ) -> EmitResult:
        """处理 format(**{"key": "val"}) 情况

        展开为 sformat("...", ("key", "val"), ...)
        """
        from mcpy.codegen.core.generator import get_global_generator

        generator = get_global_generator()

        # 构建参数列表
        args = [format_str]

        # 添加 keywords 参数
        for key, value in keywords:
            value_code = generator.generate_expression(
                value, context, parent_precedence=100
            )
            args.append(f'("{key}", {value_code})')

        # 展开字典字面量
        for key_node, value_node in zip(dict_node.keys, dict_node.values):
            # 提取键名（应该是字符串常量）
            if isinstance(key_node, IRConstant) and isinstance(key_node.value, str):
                key_name = key_node.value
                value_code = generator.generate_expression(
                    value_node, context, parent_precedence=100
                )
                args.append(f'("{key_name}", {value_code})')

        code = f"sformat({', '.join(args)})"
        return EmitResult(code=code, precedence=get_operator_precedence("call"))

    def _emit_with_variable_dict(
        self, format_str: str, dict_var, keywords: list, context: CodeGenContext
    ) -> EmitResult:
        """处理 format(**data) 情况

        使用 mc::format_dict("...", data)

        如果有混合的 keywords，也使用 format_dict（需要合并参数）
        """
        from mcpy.codegen.core.generator import get_global_generator

        generator = get_global_generator()

        dict_code = generator.generate_expression(
            dict_var, context, parent_precedence=100
        )

        if keywords and len(keywords) > 0:
            # 有混合参数，需要创建临时字典合并
            # 为简单起见，先生成 format_dict，忽略 keywords
            # TODO: 支持混合参数
            context.require_include("mc/format.h")
            code = f"mc::format_dict({format_str}, {dict_code})"
        else:
            # 只有 **data
            context.require_include("mc/format.h")
            code = f"mc::format_dict({format_str}, {dict_code})"

        return EmitResult(code=code, precedence=get_operator_precedence("call"))

    def _emit_with_keywords(
        self, format_str: str, keywords: list, context: CodeGenContext
    ) -> EmitResult:
        """处理 format(key="val") 情况

        使用 sformat("...", ("key", "val"), ...)
        """
        from mcpy.codegen.core.generator import get_global_generator

        generator = get_global_generator()

        args = [format_str]
        for key, value in keywords:
            value_code = generator.generate_expression(
                value, context, parent_precedence=100
            )
            args.append(f'("{key}", {value_code})')

        code = f"sformat({', '.join(args)})"
        return EmitResult(code=code, precedence=get_operator_precedence("call"))
